﻿// -----------------------------------------------------------------------
// <copyright file="XmlSerializationHelper.cs" company="Microsoft">
//    Not likely
// </copyright>
// -----------------------------------------------------------------------

namespace StatePersistence.Implementation
{
    using System;
    using System.Collections.Generic;
    using System.Globalization;
    using System.IO;
    using System.Text;
    using System.Xml;
    using System.Xml.Serialization;

    /// <summary>
    /// Helper for xml serialization
    /// </summary>
    public static class XmlSerializationHelper
    {
        #region Public Methods

        /// <summary>
        /// De-serializes xml into the specified .net type
        /// </summary>
        /// <param name="path">The path to the xml file to de-serialize</param>
        /// <typeparam name="T">The type which will contain the de-serialized xml</typeparam>
        /// <returns>The type representing the de-serialized xml</returns>
        public static T DeserializeXmlFile<T>(string path)
        {
            // Load the xml file into an XElement
            using (var reader = new XmlTextReader(path))
            {
                // Read the XML
                var xmlSer = new XmlSerializer(typeof(T));

                // Cast the deserialized xml to the type of dto and return
                return (T)xmlSer.Deserialize(reader);
            }
        }

        /// <summary>
        /// De-serializes xml into the specified .net type
        /// </summary>
        /// <typeparam name="T">The type which will contain the de-serialized xml</typeparam>
        /// <param name="path">The path to the xml file to de-serialize</param>
        /// <param name="xmlSerializer">The XML serializer.</param>
        /// <returns>The type representing the de-serialized xml</returns>
        public static T DeserializeXmlFile<T>(
            string path,
            XmlSerializer xmlSerializer)
        {
            if (xmlSerializer == null)
            {
                throw new ArgumentNullException("xmlSerializer");
            }

            // Load the xml file into an XElement
            using (var reader = new XmlTextReader(path))
            {
                // Cast the deserialized xml to the type of dto and return
                return (T)xmlSerializer.Deserialize(reader);
            }
        }

        /// <summary>
        /// Serializes the specified object into an xml string
        /// </summary>
        /// <typeparam name="T">The type of object that will be serialized</typeparam>
        /// <param name="objectToSerialize">The object to serialize.</param>
        /// <returns>The object serialized as an xml string</returns>
        public static string Serialize<T>(T objectToSerialize)
        {
            var serializer = new XmlSerializer(typeof(T));
            var writer = new StringWriter(CultureInfo.CurrentCulture);

            serializer.Serialize(writer, objectToSerialize);
            writer.Flush();

            return writer.ToString();
        }

        /// <summary>
        /// Serializes the specified object into an xml string
        /// </summary>
        /// <param name="value">The object to serialize.</param>
        /// <param name="xmlSerializer">The XML serializer.</param>
        /// <returns>The object serialized as an xml string</returns>
        public static string Serialize(object value, XmlSerializer xmlSerializer)
        {
            using (var writer = new StringWriter(CultureInfo.CurrentCulture))
            {
                xmlSerializer.Serialize(writer, value);
                writer.Flush();

                return writer.ToString();
            }
        }

        /// <summary>
        /// Serializes the specified object into an xml string
        /// </summary>
        /// <typeparam name="T">The type of object that will be serialized</typeparam>
        /// <param name="objectToSerialize">The object to serialize.</param>
        /// <param name="xmlSerializer">The XML serializer</param>
        /// <param name="namespaces">The namespaces</param>
        /// <returns>The object serialized as an xml string</returns>
        public static string Serialize<T>(
            T objectToSerialize,
            XmlSerializer xmlSerializer,
            XmlSerializerNamespaces namespaces)
        {
            using (var writer = new StringWriter(CultureInfo.CurrentCulture))
            {
                if (namespaces != null)
                {
                    xmlSerializer.Serialize(writer, objectToSerialize, namespaces);
                }
                else
                {
                    xmlSerializer.Serialize(writer, objectToSerialize);
                }

                writer.Flush();

                return writer.ToString();
            }
        }

        /// <summary>
        /// Serializes the specified values.
        /// Useful for creating simple xml for parsing in ids etc to stored procedures.
        /// </summary>
        /// <typeparam name="T">The type to serialize</typeparam>
        /// <param name="values">The values.</param>
        /// <param name="rootName">Name of the root element.</param>
        /// <param name="elementName">Name of the value element.</param>
        /// <returns>the class serialized as a string</returns>
        public static string Serialize<T>(IEnumerable<T> values, string rootName, string elementName)
        {
            var xml = new StringBuilder();

            var settings = new XmlWriterSettings { Indent = true };
            using (XmlWriter xmlWriter = XmlWriter.Create(xml, settings))
            {
                xmlWriter.WriteStartElement(rootName);

                foreach (T value in values)
                {
                    xmlWriter.WriteStartElement(elementName);
                    xmlWriter.WriteString(value.ToString());
                    xmlWriter.WriteEndElement();
                }

                xmlWriter.WriteEndElement();
            }

            return xml.ToString();
        }

        #endregion
    }
}
